package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.TsCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    @TsCache(prefix = "album:stat:")
    public AlbumStatVo getAlbumStatVo(Long albumId) {
        //  调用mapper 层；
        return albumInfoMapper.selectAlbumStatVo(albumId);
    }

    @Override
    public List<AlbumInfo> findUserAllAlbumList() {
        //  select * from album_info where user_id = ? and is_deleted = 0;
        //  最好有分页功能;
        Page<AlbumInfo> albumInfoPage = new Page<>(1, 20);
        //        List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(null);
        Page<AlbumInfo> infoPage = albumInfoMapper.selectPage(albumInfoPage, new LambdaQueryWrapper<AlbumInfo>().orderByDesc(AlbumInfo::getId));
        return infoPage.getRecords();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
        //  直接修改album_info;
        //  albumInfoMapper.updateById(); == this.updateById();
        AlbumInfo albumInfo = new AlbumInfo();
        //  赋值：
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        albumInfo.setId(albumId);
        albumInfoMapper.updateById(albumInfo);
        //  album_attribute_value 先删除，再新增;
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
        //	album_attribute_value
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //	判断
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
            //	循环遍历保存数据
            for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
                //	创建对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                //	属性拷贝；
                BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
                //	赋值专辑Id
                albumAttributeValue.setAlbumId(albumInfo.getId());
                //	循环遍历执行insert into values (?,?,?);insert into values (?,?,?);
                //	可以将其改为批量保存; insert into values (?,?,?) (?,?,?)
                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }
        //  判断isOpen = 0; 或 1;
        if ("1".equals(albumInfoVo.getIsOpen())) {
            //  上架; 发送的内容由消费者决定!
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumId);
            //  本质：应该在审核通过之后；
            RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
            bloomFilter.add(albumId);
        } else {
            //  下架; 发送的内容由消费者决定!
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, albumId);
        }
    }

    @Override
    @TsCache(prefix = RedisConstant.ALBUM_INFO_PREFIX)
    public AlbumInfo getAlbumInfo(Long albumId) {
         return getAlbumInfoDB(albumId);
        //  查询数据库之前，先查询缓存; 缓存没有查询数据库!  查询数据库之前+加锁! Redisson
        //  定义缓存的key
        //        String skuKey = RedisConstant.ALBUM_INFO_PREFIX + albumId;
        //        try {
        //            //  利用缓存的客户端查询数据 set key value; key=xxx; value=AlbumInfo
        //            AlbumInfo albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(skuKey);
        //            //  判断缓存中是否有数据！
        //            if (null == albumInfo) {
        //                //  获取锁之前，在判断缓存中是否有数据;
        //                //            albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(skuKey);
        //                //            if (null != albumInfo) {
        //                //                System.out.println("缓存有数据...");
        //                //                return albumInfo;
        //                //            }
        //                //  缓存中没有数据;
        //                //  定义一个锁的key
        //                String lockKey = RedisConstant.ALBUM_LOCK_SUFFIX + albumId;
        //                RLock lock = redissonClient.getLock(lockKey);
        //                //  获取锁之前，在判断缓存中是否有数据;
        //                albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(skuKey);
        //                if (null != albumInfo) {
        //                    System.out.println("缓存有数据...");
        //                    return albumInfo;
        //                }
        //                //  上锁代码
        //                lock.lock();
        //                try {
        //                    //  业务逻辑;
        //                    albumInfo = getAlbumInfoDB(albumId);
        //                    //  判断一下当前这个专辑在数据库中是否存在?
        //                    if (null == albumInfo) {
        //                        //  在缓存中存储一个空对象;
        //                        this.redisTemplate.opsForValue().set(skuKey, new AlbumInfo(), RedisConstant.ALBUM_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
        //                        return new AlbumInfo();
        //                    }
        //                    //  数据库中有数据：
        //                    this.redisTemplate.opsForValue().set(skuKey, albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS);
        //                    return albumInfo;
        //                } catch (Exception e) {
        //                    log.error("获取数据异常：" + e.getMessage());
        //                    System.out.println(e.getMessage());
        //                } finally {
        //                    //  解锁！
        //                    lock.unlock();
        //                }
        //            } else {
        //                System.out.println("缓存有数据!");
        //                //  缓存有数据
        //                return albumInfo;
        //            }
        //        } catch (Exception e) {
        //            //  发送报警邮件：钉钉！
        //            log.error("获取数据异常：" + e.getMessage());
        //        }
        //        //  查询数据库!
        //        return getAlbumInfoDB(albumId);
    }

    @Nullable
    private AlbumInfo getAlbumInfoDB(Long albumId) {
        //  获取专辑对象：album_info
        AlbumInfo albumInfo = this.getById(albumId);
        //  再获取album_attribute_value
        //  判断专辑是否存在
        if (null != albumInfo) {
            //  利用mapper 查询;
            List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
            //  存储属性与属性值数据集合
            albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
        }
        return albumInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAlbumInfo(Long albumId) {
        //	通过专辑Id获取专辑对象
        AlbumInfo albumInfo = this.getById(albumId);
        //	判断专辑对象是否存在;
        if (null == albumInfo) {
            //  或者抛出异常
            return;
        }
        this.removeById(albumId);
        //  album_stat
        //  delete from album_stat where album_id = ?;
        //  Wrapper构建删除条件的：泛型-操作哪张表的实体类
        albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, albumId));
        //  album_attribute_value
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
    }

    @Override
    public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> albumListVoPage, AlbumInfoQuery albumInfoQuery) {
        //	album_info; album_stat;
        //	使用mapper层调用sql 语句;
        return albumInfoMapper.selectUserAlbumPage(albumListVoPage, albumInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
        //	向表中插入数据; album_info album_stat(随心所欲) album_attribute_value
        //	创建对象
        AlbumInfo albumInfo = new AlbumInfo();
        //	给对象赋值; 属性拷贝；
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        //	userId 未赋值;
        albumInfo.setUserId(userId);
        //	tracks_for_free 免费试听集数; vip 免费  或 付费的情况下;
        if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())) {
            //	需要设置免费集数; 暂时给一个默认值;
            albumInfo.setTracksForFree(5);
        }
        //	专辑状态：直接写了！ 是谁创建的专辑?userId; 专辑状态应该由平台审核是否合法！
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        //	保存数据 执行完保存之后，会自动获取到当前这一条记录的主键ID; @TableId(type = IdType.AUTO)
        albumInfoMapper.insert(albumInfo);

        //	album_stat；
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);

        //	album_attribute_value
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //	判断
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
            //	循环遍历保存数据
            for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
                //	创建对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                //	属性拷贝；
                BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
                //	赋值专辑Id
                albumAttributeValue.setAlbumId(albumInfo.getId());
                //	循环遍历执行insert into values (?,?,?);insert into values (?,?,?);
                //	可以将其改为批量保存; insert into values (?,?,?) (?,?,?)
                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }
        //  判断isOpen = 0; 或 1;
        if ("1".equals(albumInfoVo.getIsOpen())) {
            //  上架; 发送的内容由消费者决定!
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
            //  本质：应该在审核通过之后；
            RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
            bloomFilter.add(albumInfo.getId());
        }
    }

    public void saveAlbumStat(Long albumId, String statPlay) {
        //	创建悐
        AlbumStat albumStat = new AlbumStat();
        //	赋值;
        albumStat.setAlbumId(albumId);
        albumStat.setStatType(statPlay);
        albumStat.setStatNum(new Random().nextInt(10000));
        //	保存数据
        albumStatMapper.insert(albumStat);
    }
}
